package com.twb.auth.service.impl;

import com.twb.auth.entity.twbApi.TwbApi;
import com.twb.auth.entity.twbApiGroup.TwbApiGroup;
import com.twb.auth.entity.twbApiGroup.dto.SearchTwbApiGroupDto;
import com.twb.auth.entity.twbApiGroup.dto.SearchTwbApiGroupTreeDto;
import com.twb.auth.entity.twbApiGroup.vo.SaveTwbApiGroupVo;
import com.twb.auth.entity.twbApiGroup.vo.SearchTwbApiGroupTreeVo;
import com.twb.auth.entity.twbApiGroup.vo.SearchTwbApiGroupVo;
import com.twb.auth.entity.twbApiGroup.vo.UpdateTwbApiGroupByIdVo;
import com.twb.auth.mapper.TwbApiGroupMapper;
import com.twb.auth.service.ITwbApiGroupService;
import com.twb.core.base.entity.TwbPageInfo;
import com.twb.core.base.service.impl.BaseService;
import com.twb.core.exception.ServiceException;
import com.twb.core.security.annotation.Auth;
import com.twb.core.util.BeanUtils;
import com.twb.core.util.ExcelUtils;
import com.twb.core.util.TwbPageUtil;
import com.twb.system.util.ExcelDataDicHandlerImpl;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.reflections.Reflections;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @author DSY
 * @ClassName TwbApiGroupService
 * @Description API分组信息service
 * @date 2021-05-13 14:35:38
 */
@Service("twbApiGroupService")
public class TwbApiGroupService extends BaseService<TwbApiGroupMapper, TwbApiGroup> implements ITwbApiGroupService {

    @Autowired
    TwbApiGroupMapper twbApiGroupMapper;

    @Autowired
    TwbApiService twbApiService;

    @Override
    public TwbPageInfo<SearchTwbApiGroupDto> searchTwbApiGroup(SearchTwbApiGroupVo vo) {
        TwbPageUtil.startPage(vo);
        List<SearchTwbApiGroupDto> list = twbApiGroupMapper.searchTwbApiGroup(vo);
        return TwbPageUtil.of(list);
    }

    @Override
    public List<SearchTwbApiGroupDto> searchTwbApiGroupList(SearchTwbApiGroupVo vo) {
        List<SearchTwbApiGroupDto> list = twbApiGroupMapper.searchTwbApiGroup(vo);
        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveTwbApiGroup(SaveTwbApiGroupVo vo) {
        String id = vo.getId();
        TwbApiGroup twbApiGroup = twbApiGroupMapper.selectById(id);
        if (twbApiGroup != null) {
            throw new ServiceException("api组编码重复，请重新输入");
        }
        Integer maxSeq = twbApiGroupMapper.getTwbApiGroupMaxSeq();
        if (null == maxSeq) {
            maxSeq = 1;
        } else {
            maxSeq++;
        }
        TwbApiGroup record = new TwbApiGroup();
        BeanUtils.copyNotNullProperties(vo, record);
        record.setId(vo.getId());
        record.setGroupSeq(maxSeq);

        return this.save(record);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateTwbApiGroupById(UpdateTwbApiGroupByIdVo vo) {
        TwbApiGroup record = twbApiGroupMapper.selectById(vo.getId());
        if (null == record) {
            throw new ServiceException("数据不存在");
        }

        BeanUtils.copyProperties(vo, record);
        return this.updateById(record);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteTwbApiGroupById(String id) {
    	TwbApi record = new TwbApi();
        record.setApiGroupId(id);
        twbApiService.remove(record);
        return this.removeById(id);
    }

    @Override
    public boolean deleteTwbApiGroupByIds(String ids) {
        String[] idArray = ids.split(",");
        for (String id : idArray) {
            TwbApi record = new TwbApi();
            record.setApiGroupId(id);
            twbApiService.remove(record);
        }
        return this.removeByIds(Arrays.asList(idArray));
    }

    @Override
    public void exportExcel(SearchTwbApiGroupVo vo, HttpServletResponse response) throws Exception {

    	TwbPageInfo<SearchTwbApiGroupDto> pageInfo = this.searchTwbApiGroup(vo);
		ExcelDataDicHandlerImpl excelDataDicHandlerImpl = new ExcelDataDicHandlerImpl();
		ExcelUtils.exportExcel(vo,"API分组信息", pageInfo.getList(), SearchTwbApiGroupDto.class, response, excelDataDicHandlerImpl);
    }

    @Override
    public int importExcel(Map<String, String> map) {
        System.out.println(map.toString());
        return 0;
    }

    @Override
    public List<SearchTwbApiGroupTreeDto> searchTwbApiGroupTree(SearchTwbApiGroupTreeVo vo) {
    	TwbPageUtil.orderBy("name asc");
        return twbApiGroupMapper.searchTwbApiGroupTree(vo);
    }

    private TwbApiGroup getTwbApiGroupByClazz(Class<?> c) {
        Api api = c.getAnnotation(Api.class);
        String[] tags = api.tags();
        String tag = "";
        if (tags != null && tags.length>0) {
            tag = tags[0];
        }
        if(StringUtils.isBlank(tag)) {
        	tag = c.getSimpleName();
        }
        String value = c.getSimpleName().replace("Controller", "").toUpperCase();
        TwbApiGroup apiGroup = new TwbApiGroup();
        apiGroup.setId(value);
        apiGroup.setName(tag);
        apiGroup.setPackageName(c.getName());
        apiGroup.setType("2");//类型=controller
        System.out.println(value + tag);
        return apiGroup;
    }

    private List<TwbApi> getTwbApiByClazz(TwbApiGroup apiGroup, Class<?> c) {
        List<TwbApi> list = new ArrayList<TwbApi>();
        RequestMapping requestMapping = c.getAnnotation(RequestMapping.class);
        String[] urls = requestMapping.value();

        int apiSeq = 0;
        
        String url = urls[0];
        Method[] methods = c.getMethods();
        for (Method m : methods) {
        	Auth auth = m.getAnnotation(Auth.class);
			if(auth != null && auth.verifyURL()==false) {
				continue;
			}
            ApiOperation apiOperation = m.getAnnotation(ApiOperation.class);
            String apiName = "";
            if (apiOperation != null) {
                apiName = apiOperation.value();
            }
            String[] paths = null;
            GetMapping getMapping = m.getAnnotation(GetMapping.class);
            if (getMapping != null) {
                paths = getMapping.value();
            }
            PostMapping postMapping = m.getAnnotation(PostMapping.class);
            if (postMapping != null) {
                paths = postMapping.value();
            }
            PutMapping putMapping = m.getAnnotation(PutMapping.class);
            if (putMapping != null) {
                paths = putMapping.value();
            }
            RequestMapping requestMapping3 = m.getAnnotation(RequestMapping.class);
            if (requestMapping3 != null) {
                paths = requestMapping3.value();
            }
            String path = "";
            if (paths != null && paths.length>0) {
                path = paths[0];
            }
            if (StringUtils.isEmpty(path)) {
                continue;
            }
            String apiType = null;
            String islog = "1";
            String methodName = m.getName();
            if (methodName.contains("list") || methodName.contains("search") || methodName.contains("get")) {
                apiType = "1";
                islog = "0";
            } else if (methodName.contains("save")) {
                apiType = "2";
            } else if (methodName.contains("update")) {
                apiType = "3";
            } else if (methodName.contains("delete")) {
                apiType = "4";
            } else {
                apiType = "1";
            }

            apiSeq++;
            TwbApi twbApi = new TwbApi();
            twbApi.setId(apiGroup.getId() + "." + m.getName().toUpperCase());
            twbApi.setApiGroupId(apiGroup.getId());
            twbApi.setApiType(apiType);
            twbApi.setDescription(apiName);
            twbApi.setIslog(islog);
            twbApi.setName(apiName);
            twbApi.setProjectId(apiGroup.getProjectId());
            twbApi.setStatus("1");
            twbApi.setUrl(url + path);
            twbApi.setIsdel(0);
            twbApi.setCreateDate(LocalDateTime.now());
            twbApi.setApiSeq(apiSeq);
            list.add(twbApi);
            System.out.println(apiGroup.getId() + "." + m.getName() + apiName + ":" + url + path);
        }

        return list;
    }

	@Override
	public boolean refreshApis(String projectId,String type,String packagesOrClasses) {
		String[] paks = packagesOrClasses.split(",");
        for (String pak : paks) {
        	if(type.equals("1")) {
        		
        		Reflections reflections = new Reflections(pak);
        		Set<Class<?>> clazzs = reflections.getTypesAnnotatedWith(RestController.class);
        		for (Class<?> c : clazzs) {
        			TwbApiGroup apiGroup = getTwbApiGroupByClazz(c);
        			apiGroup.setProjectId(projectId);
        			List<TwbApi> twbApis = getTwbApiByClazz(apiGroup, c);
        			if(twbApis.isEmpty()) {
        				continue;
        			}
        			this.removeById(apiGroup.getId());
        			SaveTwbApiGroupVo vo = new SaveTwbApiGroupVo();
        			BeanUtils.copyNotNullProperties(apiGroup, vo);
        			
        			Boolean result = this.saveTwbApiGroup(vo);
        			if (result) {
        				if (!twbApis.isEmpty()) {
        					twbApiService.saveOrUpdateBatch(twbApis);
        				}
        			}
        		}
        	}else {
        		Class<?> c = null;
                try {
                    c = Class.forName(pak);
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                    throw new ServiceException(pak + "未找到");
                }
                TwbApiGroup apiGroup = getTwbApiGroupByClazz(c);
                TwbApiGroup exist = this.getById(apiGroup.getId());
                if(exist == null) {
                	apiGroup.setProjectId(projectId);
                    this.removeById(apiGroup.getId());
                    SaveTwbApiGroupVo vo = new SaveTwbApiGroupVo();
                    BeanUtils.copyNotNullProperties(apiGroup, vo);
                    this.saveTwbApiGroup(vo);
                }
                
                List<TwbApi> twbApis = getTwbApiByClazz(apiGroup, c);
                if (!twbApis.isEmpty()) {
                    twbApiService.saveOrUpdateBatch(twbApis);
                }
        	}
        }
        return true;
	}
}
